package com.ebocy.hammer.battle;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.filter.executor.OrderedThreadPoolExecutor;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

import com.ebocy.hammer.battle.fight.FightHandler;
import com.ebocy.hammer.battle.fight.task.GameEndTask;
import com.ebocy.hammer.battle.fight.task.GameStartTask;
import com.ebocy.hammer.core.handler.HandlerManager;
import com.ebocy.hammer.core.init.MapLoader;
import com.ebocy.hammer.core.init.StaticDataLoader;
import com.ebocy.hammer.core.socket.MessageFilter;
import com.ebocy.hammer.core.socket.codecFilter.AsRequestDecoder;
import com.ebocy.hammer.core.socket.codecFilter.AsResponseEncoder;
import com.ebocy.hammer.core.socket.server.AbstractServer;
import com.ebocy.hammer.core.socket.server.ServerIoHandler;
import com.ebocy.hammer.core.util.Config;

public class BattleServer extends AbstractServer {
	private static AbstractServer server = null;
	
	private BattleServer() {
	}

	public static AbstractServer getInstance() {
		if (server == null) {
			server = new BattleServer();
		}
		return server;
	}

	@Override
	protected void initialization() {
		super.initialization();
		super.init(BattleServer.class);
		// 加载地图数据
		MapLoader.initMapData();
		// 加载静态数据
		StaticDataLoader.dataLoader();
		
		// 启动定时器，战斗开始、战斗结束
		scheduler.scheduleWithFixedDelay(new GameStartTask(), 0 * 1000, 500, TimeUnit.MILLISECONDS);
		scheduler.scheduleWithFixedDelay(new GameEndTask(), 0 * 60 * 1000, 1000, TimeUnit.MILLISECONDS);
	}

	@Override
	protected void startSocketService() {
		NioSocketAcceptor acceptor = new NioSocketAcceptor();
		acceptor.setBacklog(100);
		try {
//			acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter());
			acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(new OrderedThreadPoolExecutor(50)));
//			acceptor.getFilterChain().addLast("logger", new LogFilter());
			acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new AsResponseEncoder(),  new AsRequestDecoder()));
			acceptor.getFilterChain().addLast("message", new MessageFilter());
			acceptor.setHandler(new ServerIoHandler(acceptor));
			SocketSessionConfig sessionConfig = acceptor.getSessionConfig();
			sessionConfig.setTcpNoDelay(true);
//			sessionConfig.setIdleTime(IdleStatus.BOTH_IDLE, IDELTIMEOUT);
			acceptor.bind(new InetSocketAddress(Config.serverPort));
		} catch (IOException e) {
			e.printStackTrace();
			logger.error("socket service start failed！port=" + Config.serverPort, e);
			System.exit(0);
		}
		logger.info("socket  started on port " + Config.serverPort);
	}

	/**
	 * 注册业务处理器
	 */
	@Override
	protected void registerHandlers() {
		/** 战斗处理器 */
		HandlerManager.registerHandler(FightHandler.getInstance());
		logger.info("业务处理器注册完成！");
	}

	@Override
	protected void checkServer() {
		logger.info("服务器状态检查完成！");
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		final AbstractServer server = BattleServer.getInstance();
		server.startServer();

		// HeartBeatRunner beatRunner = new HeartBeatRunner();
		// try {
		// beatRunner.run();
		// } catch (Exception e) {
		// logger.error("定时任务启动失败！", e);
		// System.exit(0);
		// }

		// 建立与world服务器的连接
		// ServerConnector connector = new ServerConnector();
		// IoSession session = connector.connect(Config.worldServer,
		// ClientBattleHandler.getInstance());
		// ConnectorSender.setSession(session);

		Runtime.getRuntime().addShutdownHook(new Thread() {
			public void run() {
				logger.info("battler server id down!");
				server.stopServer();
			}
		});
	}
	
	@Override
	public void stopServer() {
		scheduler.shutdown();
		super.stopServer();
	}

}
